#include <stdio.h>
#include "base/main/main.h"
#include "base/abc/abc.h"

static const char *NtkTypeList[] = { "NONE",	"NETLIST",	"LOGIC",	"STRASH",	"OTHER" };
static const char *NtkFuncList[] = { "NONE",	"SOP",		"BDD",		"AIG",		"MAP",	"BLIFMV",	"BLACKBOX",	"OTHER" };

static int Abc_AigPiPoCheck(Abc_Ntk_t *pNtk1,Abc_Ntk_t *pNtk2)
{
	if(Abc_NtkCiNum(pNtk1) != Abc_NtkCiNum(pNtk2)) {
		printf("pNtk1's Ci=%d,",Abc_NtkCiNum(pNtk1));
		printf("pNtk2's Ci=%d\n",Abc_NtkCiNum(pNtk2));
		return 0;
	}
	if(Abc_NtkCoNum(pNtk1) != Abc_NtkCoNum(pNtk2)) {
		printf("pNtk1's Co=%d,",Abc_NtkCoNum(pNtk1));
		printf("pNtk2's Co=%d\n",Abc_NtkCoNum(pNtk2));
		return 0;
	}
	if(pNtk1->ntkType != pNtk2->ntkType) {
		printf("pNtk1's Network type=%s,",NtkTypeList[pNtk1->ntkType]);
		printf("pNtk2's Network type=%s\n",NtkTypeList[pNtk2->ntkType]);
		return 0;
	}
	if(pNtk1->ntkFunc != pNtk2->ntkFunc) {
		printf("pNtk1's Network Function type=%s,",NtkFuncList[pNtk1->ntkFunc]);
		printf("pNtk2's Network Function type=%s\n",NtkFuncList[pNtk2->ntkFunc]);
		return 0;
	}
	
	return 1;
}

extern Abc_Ntk_t * Abc_AigFromfile( char *file, int fCheck )
{
	Abc_Ntk_t *pNtk1 = NULL;
	extern Abc_Ntk_t *Optimaize_resyn2(Abc_Ntk_t *pNtk);
	
	//从文件读取电路
    pNtk1 = Io_Read( file, Io_ReadFileType(file), fCheck, 0 );

    if ( pNtk1 == NULL ) {
        return 0;
	}
	
	//将电路转化为AIG并优化
	pNtk1 = Optimaize_resyn2(pNtk1);
	
	return pNtk1;
}


static Abc_Ntk_t * Abc_AigFromTwoNtk(Abc_Ntk_t *pNtk1, Abc_Ntk_t *pNtk2)
{
	Abc_Ntk_t *pNtkNew = NULL;
	Abc_Obj_t *pObj = NULL;
	int i = 0;
	Vec_Ptr_t *vNtkCos = NULL;
	
	pNtkNew = Abc_NtkStartFrom( pNtk1, pNtk1->ntkType, pNtk1->ntkFunc );
	Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkNew);
    Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkNew);
	//pNtk1里的pCopy对应新网络的节点, 以下对pNtk2里Ci和Co的pCopy保证和pNtk1一样
	/*Abc_NtkForEachCo(pNtk2,pObj,i) {
		pObj->pCopy = Abc_NtkCo(pNtk1, i)->pCopy;
	}*/
	
	Abc_NtkForEachCi(pNtk2,pObj,i) {
		pObj->pCopy = Abc_NtkCi(pNtk1, i)->pCopy;
	}
	
	//删除多余的输出
	vNtkCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtkNew) );
	Abc_NtkForEachCo(pNtkNew,pObj,i) {
		Vec_PtrPush( vNtkCos, pObj  );
	}
	
	Vec_PtrForEachEntry( Abc_Obj_t *, vNtkCos, pObj, i ) {
		Abc_NtkDeleteObj(pObj);
	}
	Vec_PtrFree( vNtkCos );
	
	return pNtkNew;
}	

//合并两个AIG电路为一个Miter
extern Abc_Ntk_t * Abc_AigCombine2Miter( Abc_Ntk_t *pNtk1, Abc_Ntk_t *pNtk2 )
{
	Abc_Ntk_t *pNtkNew = NULL;
	Abc_Obj_t *pObj = NULL, *pMiter = NULL;
	int i = 0;
	Vec_Ptr_t *vPairs = NULL;

	//校验两个电路输入个数和输出个数是否相等
	if(Abc_AigPiPoCheck(pNtk1,pNtk2) == 0) {
		return 0;
	}
	
	Abc_NtkCleanCopy(pNtk1);
	Abc_NtkCleanCopy(pNtk2);
	
	//新建一个网络, 将两个网络重新在新网络上构建
	pNtkNew = Abc_AigFromTwoNtk( pNtk1, pNtk2 );
	
    if ( Abc_NtkIsStrash(pNtk1) )
    {
        // 复制pNtk1的网络
        Abc_AigForEachAnd( pNtk1, pObj, i ) {
            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
		}
        // relink the choice nodes
        Abc_AigForEachAnd( pNtk1, pObj, i )
            if ( pObj->pData )
                pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
		
		//复制pNtk2的网络
        Abc_AigForEachAnd( pNtk2, pObj, i ) {
            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
		}

        // relink the choice nodes
        Abc_AigForEachAnd( pNtk2, pObj, i ) {
            if ( pObj->pData ) {
                pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
			}
		}
		
		//构造miter
		vPairs = Vec_PtrAlloc( Abc_NtkCoNum(pNtk1)*2 );
		Abc_NtkForEachCo(pNtk2,pObj,i) {
			Vec_PtrPush( vPairs, Abc_ObjChild0Copy(Abc_NtkCo(pNtk1, i)) );
			Vec_PtrPush( vPairs, Abc_ObjChild0Copy(Abc_NtkCo(pNtk2, i)) );
		}
		
		pMiter = Abc_AigMiter((Abc_Aig_t *)pNtkNew->pManFunc,vPairs,0);
		Vec_PtrFree( vPairs );
		
		Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pMiter );
		
    }
	else {
		return NULL;
	}
	
	
	return pNtkNew;
}